package com.atguigu.gmall.index.service;


import com.alibaba.fastjson.JSON;
import com.atguigu.core.bean.Resp;
import com.atguigu.gmall.index.annotation.GmallCache;
import com.atguigu.gmall.index.fegin.GmallPmsClient;
import com.atguigu.gmall.pms.entity.CategoryEntity;
import com.atguigu.gmall.pms.vo.CategoryEntityVO;
import io.swagger.models.properties.PropertyBuilder;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class IndexService {

    //使用缓存,相比较restTemplate要好
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;//Redisson

    //缓存的前缀
    private static final String KEY_PREFIX="index:cates";
    @Autowired
    private GmallPmsClient gmallPmsClient;

    public List<CategoryEntity> queryLvllCategories() {

        Resp<List<CategoryEntity>> listResp = gmallPmsClient.queryCategoriesByPidOrLevel(1, null);//父id变为null
        return listResp.getData();
    }

    @GmallCache(prefix = KEY_PREFIX,timeout = 7200,randomTime = 100)
    public List<CategoryEntityVO> querySubCategories(Long pid) {

//        //1、判断缓存中有没有
//        String cateJson = this.redisTemplate.opsForValue().get(KEY_PREFIX + pid);//返回的是分类的json
//        //2、有，直接返回
//        if(!StringUtils.isEmpty(cateJson)){
//            return JSON.parseArray(cateJson,CategoryEntityVO.class);
//        }
//
//        //加分布式锁，然后在做一次判断，解决缓存击穿问题
//        RLock rLock = this.redissonClient.getLock("lock" + pid);//+pid是为了之锁一个
//        rLock.lock();//加锁
//        //1、判断缓存中有没有
//        String cateJson2 = this.redisTemplate.opsForValue().get(KEY_PREFIX + pid);//返回的是分类的json
//        //2、有，直接返回
//        if(!StringUtils.isEmpty(cateJson2)){
//
//            //有了直接返回了，就没释放锁
//            rLock.unlock();//释放锁
//            return JSON.parseArray(cateJson2,CategoryEntityVO.class);
//        }

        //3、没有，查询并放入缓存
        Resp<List<CategoryEntityVO>> subCategoryResp = this.gmallPmsClient.querySubCategory(pid);
        List<CategoryEntityVO> categoryRespData = subCategoryResp.getData();
        //放入缓存,放入前需要序列化,加上一个5以内的随机数，解决缓存雪崩问题，防止同时失效
//        this.redisTemplate.opsForValue().set(KEY_PREFIX+ pid,JSON.toJSONString(categoryRespData),7+new Random().nextInt(5) ,TimeUnit.DAYS);
//
//        rLock.unlock();//释放锁
        return categoryRespData;
    }

    public void testLock() {

        RLock lock = this.redissonClient.getLock("lock"); // 只要锁的名称相同就是同一把锁
        lock.lock(); // 加锁

        // 查询redis中的num值
        String value = this.redisTemplate.opsForValue().get("num");
        // 没有该值return
        if (StringUtils.isBlank(value)) {
            return;
        }
        // 有值就转成成int
        int num = Integer.parseInt(value);
        // 把redis中的num值+1
        this.redisTemplate.opsForValue().set("num", String.valueOf(++num));

        lock.unlock(); // 解锁
    }
}
